package com.atguigu.tingshu.album.service.impl;

import java.math.BigDecimal;

import com.atguigu.tingshu.album.mapper.AlbumAttributeValueMapper;
import com.atguigu.tingshu.album.mapper.AlbumStatMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.service.AlbumAttributeValueService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.model.album.AlbumAttributeValue;
import com.atguigu.tingshu.model.album.AlbumStat;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.query.album.AlbumInfoQuery;
import com.atguigu.tingshu.vo.album.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.collect.Lists;

import java.util.Date;
import java.util.List;

import com.google.common.collect.Maps;

import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.service.AlbumInfoService;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class AlbumInfoServiceImpl extends ServiceImpl<AlbumInfoMapper, AlbumInfo> implements AlbumInfoService {

    @Autowired
    private AlbumInfoMapper albumInfoMapper;

    @Autowired
    private AlbumStatMapper albumStatMapper;

    @Autowired
    private AlbumAttributeValueService albumAttributeValueService;
    @Autowired
    private AlbumAttributeValueMapper albumAttributeValueMapper;
    @Autowired
    private TrackInfoMapper trackInfoMapper;
    @Autowired
    private AlbumInfoService albumInfoService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveAlbumInfo(AlbumInfoVo albumInfoVo) {

        AlbumInfoServiceImpl proxyObject = (AlbumInfoServiceImpl) AopContext.currentProxy();

        // 入库 tingshu_album表 (album_info album_attribute_value)
        Long userId = AuthContextHolder.getUserId();

        // 1. 保存基本信息表（album_info表中插入数据）
        // 实体类专门用来和数据库列做映射
        AlbumInfo albumInfo = new AlbumInfo();
        BeanUtils.copyProperties(albumInfoVo, albumInfo);
        // 额外赋值一次(userId)
        albumInfo.setUserId(userId);
        // 默认审核通过
        albumInfo.setStatus(SystemConstant.ALBUM_STATUS_PASS);

        // 获取专辑的付费类型(0101(免费) 0102(vip免费) 0103(付费))
        String payType = albumInfoVo.getPayType();
        if (!payType.equals(SystemConstant.ALBUM_PAY_TYPE_FREE)) {
            // 默认给这个专辑设置5集免费声音
            albumInfo.setTracksForFree(5);
        }

        int insert = albumInfoMapper.insert(albumInfo);
        log.info("保存专辑信息：{}", insert > 0 ? "success" : "fail");


        // 2. 保存专辑的标签信息（album_attribute_value表中插入数据）
        // 获取选择的标签信息
        List<AlbumAttributeValueVo> albumAttributeValueVoList = albumInfoVo.getAlbumAttributeValueVoList();
        List<AlbumAttributeValue> albumAttributeValueList = albumAttributeValueVoList.stream().map(albumAttributeValueVo -> {
            AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();
            albumAttributeValue.setAlbumId(albumInfo.getId());
            albumAttributeValue.setAttributeId(albumAttributeValueVo.getAttributeId());
            albumAttributeValue.setValueId(albumAttributeValueVo.getValueId());
            return albumAttributeValue;
        }).toList();
        if (!CollectionUtils.isEmpty(albumAttributeValueList)) {
            boolean result = albumAttributeValueService.saveBatch(albumAttributeValueList);
            log.info("保存专辑标签信息:{}", result ? "success" : "fail");
        }
        // 3. 保存专辑的统计（album_stat）
        //tips:
        //1>saveAlbumStat(albumInfo.getId()); 方法上不加 @Transactional ,正常使用
        //2>proxyObject.saveAlbumStat(albumInfo.getId()); 方法上加 @Transactional, 需要使用的是代理对象调用该方法

        // saveAlbumStat(albumInfo.getId());
        proxyObject.saveAlbumStat(albumInfo.getId());
    }

    @Override
    public IPage<AlbumListVo> findUserAlbumPage(IPage<AlbumListVo> pageParam, AlbumInfoQuery albumInfoQuery) {
        return albumInfoMapper.findUserAlbumPage(pageParam, albumInfoQuery);
    }

    @Override
    public AlbumInfo getAlbumInfo(Long albumId) {

        //1. 根据专辑id查询专辑基本信息
        AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
        if (albumInfo == null) {
            throw new GuiguException(201, "专辑不存在");
        }

        //2. 查询专辑的标签信息（属性id和属性值id）
        List<AlbumAttributeValue> albumAttributeValues = albumAttributeValueMapper.selectList(
                new LambdaQueryWrapper<AlbumAttributeValue>()
                        .eq(AlbumAttributeValue::getAlbumId, albumId));
        albumInfo.setAlbumAttributeValueVoList(albumAttributeValues);

        return albumInfo;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateAlbumInfo(Long albumId, AlbumInfoVo albumInfoVo) {
        // 1. 修改基本信息
        // 1.1. 根据专辑id查询专辑的旧数据
        AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
        if (albumInfo == null) {
            throw new GuiguException(201, "专辑不存在");
        }
        BeanUtils.copyProperties(albumInfoVo, albumInfo);

        if (SystemConstant.ALBUM_PAY_TYPE_FREE.equals(albumInfoVo.getPayType())) {
            albumInfo.setPrice(new BigDecimal("0.00"));
            albumInfo.setVipDiscount(new BigDecimal("-1.00"));
            albumInfo.setDiscount(new BigDecimal("-1.00"));
            albumInfo.setTracksForFree(0);
        } else {
            albumInfo.setTracksForFree(5);
        }

        int i = albumInfoMapper.updateById(albumInfo);
        log.info("修改专辑信息:{}", i > 0 ? "success" : "fail");

        // 2. 修改专辑的标签信息
        // 2.1 删除该专辑的老标签信息
        int delete = albumAttributeValueMapper.delete(
                new LambdaQueryWrapper<AlbumAttributeValue>()
                        .eq(AlbumAttributeValue::getAlbumId, albumId));
        log.info("删除专辑标签信息:{}", delete > 0 ? "success" : "fail");
        // 2.2 插入该专辑的新标签信息
        List<AlbumAttributeValue> albumAttributeValueList = albumInfoVo.getAlbumAttributeValueVoList().stream().map(albumAttributeValueVo -> {
            AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();
            albumAttributeValue.setAlbumId(albumId);
            albumAttributeValue.setAttributeId(albumAttributeValueVo.getAttributeId());
            albumAttributeValue.setValueId(albumAttributeValueVo.getValueId());
            return albumAttributeValue;
        }).toList();

        if (!CollectionUtils.isEmpty(albumAttributeValueList)) {
            boolean result = albumAttributeValueService.saveBatch(albumAttributeValueList);
            log.info("修改专辑标签信息:{}", result ? "success" : "fail");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void removeAlbumInfo(Long albumId) {
        //1. 删除专辑的基本信息
        //删除专辑基本信息前需要判断改专辑下是否还有音频
        Long count = trackInfoMapper.selectCount(new LambdaQueryWrapper<TrackInfo>().eq(TrackInfo::getAlbumId, albumId));
        if (count > 0) {
            throw new GuiguException(201, "该专辑下还有音频，不能删除");
        }
        int i = albumInfoMapper.deleteById(albumId);
        log.info("删除专辑基本信息:{}", i > 0 ? "success" : "fail");

        //2. 删除专辑的标签信息
        int delete = albumAttributeValueMapper.delete(
                new LambdaQueryWrapper<AlbumAttributeValue>()
                        .eq(AlbumAttributeValue::getAlbumId, albumId));
        log.info("删除专辑标签信息:{}", delete > 0 ? "success" : "fail");

        //3. 删除专辑的统计信息
        int result = albumStatMapper.delete(
                new LambdaQueryWrapper<AlbumStat>()
                        .eq(AlbumStat::getAlbumId, albumId));
        log.info("删除专辑统计信息:{}", result > 0 ? "success" : "fail");
    }

    @Override
    public List<AlbumInfo> findUserAllAlbumList(Long userId) {
        return albumInfoMapper.selectList(
                new LambdaQueryWrapper<AlbumInfo>()
                        .eq(AlbumInfo::getUserId, userId)
                        .orderByDesc(AlbumInfo::getCreateTime));
    }

    @Override
    public AlbumStatVo getAlbumStat(Long albumId) {
        return albumInfoMapper.getAlbumStat(albumId);
    }

    @Override
    public List<TrackListVo> getTrackList(List<Long> trackIdList) {
        List<TrackInfo> trackInfos = trackInfoMapper.selectBatchIds(trackIdList);
        return trackInfos.stream().map(trackInfo -> {
            TrackListVo trackListVo = new TrackListVo();
            BeanUtils.copyProperties(trackInfo, trackListVo);
            trackListVo.setTrackId(trackInfo.getId());
            // 根据专辑id获取到专辑信息
            AlbumInfo albumInfo = albumInfoService.getAlbumInfo(trackInfo.getAlbumId());
            trackListVo.setCoverUrl(albumInfo.getCoverUrl());
            return trackListVo;
        }).toList();
    }

    @Override
    public List<Long> getAlbumInfoIdList() {
        List<AlbumInfo> albumInfoList = albumInfoMapper.selectList(null);
        return albumInfoList.stream().map(AlbumInfo::getId).toList();
    }

    @Override
    public AlbumInfo getAlbumInfoByTrackId(Long trackId) {
        TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
        if (trackInfo == null){
            throw new GuiguException(201, "该声音不存在!");
        }
        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
        if (albumInfo == null){
            throw new GuiguException(201, "该声音对应的专辑不存在!");
        }
        return albumInfo;
    }

    @Transactional
    public void saveAlbumStat(Long albumId) {
        List<String> albumStatus = List.of(SystemConstant.ALBUM_STAT_PLAY,
                SystemConstant.ALBUM_STAT_SUBSCRIBE,
                SystemConstant.ALBUM_STAT_BROWSE,
                SystemConstant.ALBUM_STAT_COMMENT);
        for (String status : albumStatus) {
            AlbumStat albumStat = new AlbumStat();
            albumStat.setAlbumId(albumId);
            albumStat.setStatType(status);
            albumStat.setStatNum(0);
            albumStatMapper.insert(albumStat);
        }
    }

}
